package com.joolun.web.controller.scrm;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.joolun.common.annotation.Log;
import com.joolun.common.core.controller.BaseController;
import com.joolun.common.core.domain.AjaxResult;
import com.joolun.common.core.domain.entity.SysDept;
import com.joolun.common.core.domain.entity.SysUser;
import com.joolun.common.core.page.TableDataInfo;
import com.joolun.common.enums.BusinessType;
import com.joolun.common.utils.SecurityUtils;
import com.joolun.common.utils.poi.ExcelUtil;
import com.joolun.system.service.ISysDeptService;
import com.joolun.web.huantuo.MD5Generator;
import com.joolun.web.huantuo.MTCloud;
import com.joolun.weixin.entity.ZbVideo;
import com.joolun.weixin.entity.vo.UploadResultVo;
import com.joolun.weixin.service.IZbVideoService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * 视频库Controller
 * 
 * @author joolun
 * @date 2025-04-24
 */
@RestController
@RequestMapping("/zb/video")
public class ZbVideoController extends BaseController
{
    @Autowired
    private IZbVideoService zbVideoService;
    @Autowired
    private ISysDeptService deptService;

    // 使用ObjectMapper库解析JSON字符串
    ObjectMapper mapper = new ObjectMapper();
    // 临时存储目录
    private static final Path TEMP_DIR = Paths.get(System.getProperty("java.io.tmpdir"), "uploads");
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);
    private final Map<String, Consumer<UploadResultVo>> callbackRegistry = new ConcurrentHashMap<>();

    // 初始化临时目录
    static {
        try {
            if (!Files.exists(TEMP_DIR)) {
                Files.createDirectories(TEMP_DIR);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 根据登录用户获取openID和openToken
    public MTCloud getOpenIDAndOpenToken(){
        // 获取当前登录的用户信息
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 获取当前登录用户的部门
        SysDept dept = user.getDept();
        // 获取父级部门id
        Long parentId = dept.getParentId();
        // 获取父级部门对象
        SysDept parentDept = deptService.selectDeptById(parentId);
        System.out.println("OpenIdHt---------------" + parentDept.getOpenIdHt());
        if((parentDept.getOpenIdHt() != null && parentDept.getOpenIdHt() != "") && (parentDept.getOpenTokenHt() != null && parentDept.getOpenTokenHt() != "")){
            // 根据用户所属公司获取公司的openID和openToken
            return new MTCloud(parentDept.getOpenIdHt(),parentDept.getOpenTokenHt());
        }
        MTCloud mtCloud = new MTCloud();
        return mtCloud;
    }
    /**
     * 查询视频库列表
     */
    @GetMapping("/list")
    public TableDataInfo list(ZbVideo zbVideo)
    {
        startPage();
        List<ZbVideo> list = zbVideoService.selectZbVideoList(zbVideo);
        return getDataTable(list);
    }

    /**
     * 导出视频库列表
     */
    @PreAuthorize("@ss.hasPermi('zb:video:export')")
    @Log(title = "视频库", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ZbVideo zbVideo)
    {
        List<ZbVideo> list = zbVideoService.selectZbVideoList(zbVideo);
        ExcelUtil<ZbVideo> util = new ExcelUtil<ZbVideo>(ZbVideo.class);
        util.exportExcel(response, list, "视频库数据");
    }

    /**
     * 获取视频库详细信息
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        HashMap<Object,Object> map = new HashMap<>();
        try {
            // 欢拓接口
            MTCloud mtCloud = getOpenIDAndOpenToken();
            // 查询欢拓视频播放地址
            String htResult = mtCloud.videoGet(id,3600);
            // 将返回结果转换为map
            Map<String, Object> htMap = mapper.readValue(htResult, Map.class);
            Long code = Long.parseLong(htMap.get("code").toString());
            // 之前已经上传过的视频
            if(code == 0){
                Map<String, Object> dataMap = (Map<String, Object>) htMap.get("data");
                map.put("htVideo",dataMap);
                map.put("zbVideo",zbVideoService.selectZbVideoById(id));
            }else{
                // 返回上传地址
                Map<String, Object> dataMap = (Map<String, Object>) htMap.get("data");
                System.out.println("获取失败  ==>" + dataMap);
                return AjaxResult.error("预览失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return success(map);
    }

    /**
     * 新增视频库
     */
//    @PreAuthorize("@ss.hasPermi('zb:video:add')")
    @Log(title = "视频库", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody ZbVideo zbVideo)
    {
        zbVideo.setType("伪直播");
        zbVideo.setStatus("转码完成");
        zbVideo.setCreateBy(getUsername());
        return toAjax(zbVideoService.insertZbVideo(zbVideo));
    }
    /**
     * 获取上传地址
     */
    @PostMapping("/upload/url")
    public AjaxResult getUploadUrl(@RequestParam("fileName") String fileName,@RequestParam("md5Str") String md5Str)
    {
        try {
            // 欢拓接口
            MTCloud mtCloud = getOpenIDAndOpenToken();
            HashMap<Object,Object> options = new HashMap<>();
            // 获取上传地址
            String htResult = mtCloud.videoGetUploadUrl("835283",1, fileName, md5Str, options);
            // 将返回结果转换为map
            Map<String, Object> htMap = mapper.readValue(htResult, Map.class);
            // 访问内部code字段
            Long code = Long.parseLong(htMap.get("code").toString());
            // 之前已经上传过的视频
            if(code == 1281){
                Map<String, Object> dataMap = (Map<String, Object>) htMap.get("data");
                String videoId = dataMap.get("videoId").toString();
                return AjaxResult.error("之前已经上传过相同的视频文件,视频id:" + videoId);
            }else{
                // 返回上传地址
                Map<String, Object> dataMap = (Map<String, Object>) htMap.get("data");
//                String resumeUploadUrl = dataMap.get("resumeUploadUrl").toString();
                return AjaxResult.success(dataMap);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取失败");
        }
    }


    /**
     * 修改视频库
     */
    @PreAuthorize("@ss.hasPermi('zb:video:edit')")
    @Log(title = "视频库", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ZbVideo zbVideo)
    {
        try {
            // 欢拓接口
            MTCloud mtCloud = getOpenIDAndOpenToken();
            // 先请求修改欢拓
            String htResult = mtCloud.videoUpdate(zbVideo.getId(),zbVideo.getTitle());
            // 将返回结果转换为map
            Map<String, Object> htMap = mapper.readValue(htResult, Map.class);
            Long code = Long.parseLong(htMap.get("code").toString());
            if(code == 0){
                zbVideo.setCreateBy(getUsername());
                return toAjax(zbVideoService.updateZbVideo(zbVideo));
            }else{
                return toAjax(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return toAjax(0);
    }

    /**
     * 删除视频库
     */
    @PreAuthorize("@ss.hasPermi('zb:video:remove')")
    @Log(title = "视频库", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        try {
            // 欢拓接口
            MTCloud mtCloud = getOpenIDAndOpenToken();
            // 先请求删除欢拓
            String htResult = mtCloud.videoDelete(ids[0]);
            // 将返回结果转换为map
            Map<String, Object> htMap = mapper.readValue(htResult, Map.class);
            Long code = Long.parseLong(htMap.get("code").toString());
            if(code == 0){
                return toAjax(zbVideoService.deleteZbVideoByIds(ids));
            }else{
                return toAjax(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return toAjax(0);
    }

//    /**
//     * 处理视频分片上传
//     * uuid前端生成的文件唯一标识
//     */
//    @PostMapping("/api/upload")
//    public AjaxResult handleFileUpload(@RequestParam("file") MultipartFile file
//            ,@RequestParam("uuid") String uuid
//            ,@RequestParam("chunkIndex") int chunkIndex
//            ,@RequestParam("totalChunks") int totalChunks
//            ,@RequestParam("md5Str") String md5Str)
//    {
//        if (file.isEmpty()) {
//            return  AjaxResult.error("上传的文件为空");
//        }
//        try {
//            // 获取文件名
//            String originalFilename = file.getOriginalFilename();
//            // 获取视频文件md5
//            //  String md5 = MD5Generator.getFileMD5(file);
//            HashMap<Object,Object> options = new HashMap<>();
//            // 获取上传地址
//            String htResult = mtCloud.videoGetUploadUrl("835283",1, originalFilename, md5Str, options);
//            // 将返回结果转换为map
//            Map<String, Object> htMap = mapper.readValue(htResult, Map.class);
//            // 访问内部code字段
//            Long code = Long.parseLong(htMap.get("code").toString());
//            // 之前已经上传过的视频
//            if(code == 1281){
//                Map<String, Object> dataMap = (Map<String, Object>) htMap.get("data");
//                String videoId = dataMap.get("videoId").toString();
//                return AjaxResult.error("之前已经上传过相同的视频文件，视频id：" + videoId);
//            }else{
//                // 创建文件分片的临时目录
//                Path chunkDir = TEMP_DIR.resolve(uuid);
//                if (!Files.exists(chunkDir)) {
//                    Files.createDirectories(chunkDir);
//                }
//                // 保存分片到临时目录
//                Path chunkPath = chunkDir.resolve("part_" + chunkIndex);
//                file.transferTo(chunkPath.toFile());
//                // 当是最后一个请求时，返回保存分片的路径
//                // 返回临时路径（实际项目中通常返回状态码，而非路径）
//                return AjaxResult.success(chunkPath.toString());
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//            return AjaxResult.error("上传失败");
//        }
//    }

//    /**
//     * 合并分片
//     */
//    @PostMapping("/merge")
//    public AjaxResult mergeChunks(
//            @RequestParam("uuid") String uuid,
//            @RequestParam("fileName") String fileName,
//            @RequestParam("totalChunks") int totalChunks
//    ) {
//        try {
//            Path chunkDir = TEMP_DIR.resolve(uuid);
//            Path targetFile = Paths.get("uploads", fileName);
//            // 创建目标文件
//            if (!Files.exists(targetFile.getParent())) {
//                Files.createDirectories(targetFile.getParent());
//            }
//            Files.createFile(targetFile);
//            // 按顺序合并分片
//            try (WritableByteChannel targetChannel = Files.newByteChannel(targetFile, StandardOpenOption.WRITE)) {
//                for (int i = 0; i < totalChunks; i++) {
//                    Path chunkPath = chunkDir.resolve("part_" + i);
//                    if (Files.exists(chunkPath)) {
//                        try (ReadableByteChannel chunkChannel = Files.newByteChannel(chunkPath)) {
//                            ByteBuffer buffer = ByteBuffer.allocate(8192);
//                            while (chunkChannel.read(buffer) != -1) {
//                                buffer.flip();
//                                targetChannel.write(buffer);
//                                buffer.clear();
//                            }
//                        }
//                    }
//                }
//            }
//            // 合并完成后删除临时目录
//            Files.walk(chunkDir).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
//            // 合并后，实现欢拓上传操作
//            String uploadId = startUpload(targetFile,fileName, result -> {
//                if (result.isSuccess()) {
//                    // 上传完成，删除服务器缓存视频
//                    if (Files.exists(targetFile)) {
//                        try {
//                            Files.delete(targetFile);
//                        } catch (IOException e) {
//                            e.printStackTrace();
//                        }
//                        System.out.println(fileName + " 缓存文件已删除" );
//                    } else {
//                        System.out.println(fileName + " 文件不存在");
//                    }
//                    // 添加后台视频库数据
//                    ZbVideo zbVideo = new ZbVideo();
//                    zbVideo.setId(Long.parseLong(result.getVideoId()));
//                    zbVideo.setTitle(fileName);
//                    zbVideo.setUrl(result.getUrl());
//                    zbVideo.setStatus("转码完成");
//                    zbVideoService.insertZbVideo(zbVideo);
//                    System.out.println(fileName + " 上传成功" + result.getVideoId());
//                } else {
//                    // 处理失败结果
//                    System.err.println(fileName + "上传失败: " + result.getBid());
//                }
//            });
//            return AjaxResult.success(fileName + "上传已开始...");
//        } catch (Exception e) {
//            e.printStackTrace();
//            return AjaxResult.error("上传失败");
//        }
//    }
//    /**
//     * 发起上传请求并注册回调
//     */
//    public String startUpload(Path targetFile,String fileName, Consumer<UploadResultVo> callback) {
//        String uploadId = UUID.randomUUID().toString();
//        // 1. 保存回调函数
//        callbackRegistry.put(uploadId, callback);
//        // 2. 调用第三方上传接口（异步）
//        uploadToThirdPartyAsync(uploadId, fileName, targetFile);
//        return uploadId;
//    }
//    // 模拟调用第三方上传接口
//    private void uploadToThirdPartyAsync(String uploadId,String fileName, Path targetFile) {
//        scheduler.schedule(() -> {
//            try {
//                // 调用第三方上传
//                HashMap<Object,Object> course = new HashMap<>();
//                String videoResult = mtCloud.videoSegmentUpload(targetFile.toString(),"835283",1, fileName, "星辰科技", "",course);
//                // 将返回结果转换为map
//                Map<String, Object> htMap = mapper.readValue(videoResult, Map.class);
//                System.out.println("上传结果-------------" + videoResult);
//                // 访问内部code字段
//                String code = htMap.get("code").toString();
//                if("0".equals(code)){
//                    Map<String, Object> dataMap = (Map<String, Object>) htMap.get("data");
//                    String videoId = dataMap.get("videoId").toString();
//                    String bid = dataMap.get("bid").toString();
//                    String url = dataMap.get("url").toString();
//                    // 上传成功
//                    UploadResultVo result = new UploadResultVo(uploadId, videoId, true, bid, url);
//                    // 触发回调
//                    triggerCallback(result);
//                }else{
//                    // 上传失败
//                    UploadResultVo result = new UploadResultVo(uploadId, "", false, "", "");
//                    // 触发回调
//                    triggerCallback(result);
//                }
//            } catch (Exception e) {
//                // 处理异常
//                UploadResultVo result = new UploadResultVo(uploadId, "", false, e.getMessage(), "");
//                triggerCallback(result);
//            }
//        }, 0, TimeUnit.MILLISECONDS); // 立即执行（模拟异步调用）
//    }
//    // 触发回调
//    private void triggerCallback(UploadResultVo result) {
//        Consumer<UploadResultVo> callback = callbackRegistry.remove(result.getUuid());
//        if (callback != null) {
//            callback.accept(result);
//        }
//    }





}
